//
//  HTTPSURLProtocol.m
//  SinochemApp
//
//  Created by 洪志亮 on 2018/6/5.
//  Copyright © 2018年 Facebook. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "HTTPSURLProtocol.h"

static NSString * const URLProtocolHandledKey = @"这里任意字符串";

@implementation HTTPSURLProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)theRequest
{
  //FIXME: 后来的https类型的reqeust应该也要被处理
  NSString *scheme = [[theRequest URL] scheme];
  if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
        [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame))
  {
    //看看是否已经处理过了，防止无限循环
    if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:theRequest]) {
      return NO;
    }
    
    //此处做个判断,app.xxxx.com是我们项目的域名.任何不属于我们域名的不做处理,这样可以加载https://weibo.com等第三方https网页
//    if (![[[theRequest URL] host] isEqualToString:@"app.xxxx.com"]) {
//      return NO;
//    }
    
    return YES;
  }
  return NO;
}

+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
{
  NSMutableURLRequest *mutableReqeust = [request mutableCopy];
  mutableReqeust = [self redirectHostInRequset:mutableReqeust];
  return mutableReqeust;
}

- (void)startLoading
{
  //theConncetion = [[NSURLConnection alloc] initWithRequest:self.request delegate:self];
  NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
  //标示改request已经处理过了，防止无限循环
  [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
  theConncetion = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
  if (theConncetion) {
    _data = [NSMutableData data];
  }
}

- (void)stopLoading
{
  // NOTE:如有清理工作，可以在此处添加
  [theConncetion cancel];
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
{
  return [super requestIsCacheEquivalent:requestA toRequest:requestB];
}

#pragma mark - NSURLConnectionDelegate

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
  //响应服务器证书认证请求和客户端证书认证请求
  return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] ||
  [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
  NSURLCredential* credential;
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
  {
    //服务器证书认证
    credential= [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
  }
  else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
  {
    //客户端证书认证
    //TODO:设置客户端证书认证
    NSString *thePath = [[NSBundle mainBundle] pathForResource:@"ubmp_app_client" ofType:@"p12"];
    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
    SecIdentityRef identity;
    // 读取p12证书中的内容
    OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
    
//    if(result != errSecSuccess){
//        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//        return;
//    }
    
    SecCertificateRef certificate = NULL;
    SecIdentityCopyCertificate(identity, &certificate);
    
    const void *certs[] = {certificate};
    CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
    
    credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
  }
  
  if (credential != nil)
  {
    [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
  }
  else
  {
    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
  }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
  [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
  
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
  [_data appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
  [[self client] URLProtocol:self didLoadData:_data];
  [[self client] URLProtocolDidFinishLoading:self];
  
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
  [[self client] URLProtocol:self didFailWithError:error];
  
}
- (OSStatus)extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef *)identity {
  OSStatus securityErr = errSecSuccess;
  
  CFStringRef pwd = CFSTR("646800");
  const void *keys[] = {kSecImportExportPassphrase};
  const void *values[] = {pwd};
  CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  securityErr = SecPKCS12Import(inP12Data, options, &items);
  
  if (securityErr == errSecSuccess) {
    CFDictionaryRef ident = CFArrayGetValueAtIndex(items, 0);
    const void *tmpIdent = NULL;
    tmpIdent = CFDictionaryGetValue(ident, kSecImportItemIdentity);
    *identity = (SecIdentityRef)tmpIdent;
  }
  
  if (options) {
    CFRelease(options);
  }
  
  return securityErr;
}
+(NSMutableURLRequest*)redirectHostInRequset:(NSMutableURLRequest*)request
{
  if ([request.URL host].length == 0) {
    return request;
  }
  
  NSString *originUrlString = [request.URL absoluteString];
  NSLog(@"-----链接导向---------->:%@",originUrlString);
  
  NSString *originHostString = [request.URL host];
  NSRange hostRange = [originUrlString rangeOfString:originHostString];
  if (hostRange.location == NSNotFound) {
    return request;
  }
  
  //此处可以将网页中链接的域名替换为自己的域名,防止劫持.
  //    NSString *ip = @"app.xxxx.com";
  //     // 替换域名
  //    NSString *urlString;
  //    if ([originUrlString isEqualToString:@"apis.map.qq.com"]) {
  //        urlString=originUrlString;
  //    }else if ([originUrlString isEqualToString:@"weibo.com"]){
  //        urlString=originUrlString;
  //
  //    }else{
  //        urlString = [originUrlString stringByReplacingCharactersInRange:hostRange withString:ip];
  //    }
  
  //    NSURL *url = [NSURL URLWithString:originUrlString];
  //    request.URL = url;
  
  return request;
}
@end

  
  
